<?php
class Ext_Generic_Model extends Ext_Db_Table
{
    private  static $_models = array();
    /**
     * Detalle de los errores encontrados 
     *
     * @var array
     */
    protected $_errors;
    /**
     * Devuelve la instancia de un modelo.
     *
     * @param string $model
     * @return mixed
     */
    public static function get ( $model = '', $db = null )
    {
        if ( empty( $model ) ) {
            throw new Exception( "Error getting model $model" );
        }
        $model = ucfirst( $model );
        if ( ! isset( self::$_models[ $model ] ) ) {
            self::$_models[ $model ] = new $model( $db );
        }
        return self::$_models[ $model ];
    }
    /**
     * Este metodo esta en modo testing.
     * Ahora el tipo que recibe se transforma en entero debido a un conflicto
     * con el metodo fetchRow que devolvia un string, 
     * Ademas se agrego la posibilidad de hacer un FetchRow, sin tener sequence
     * Ya que usa un fetchRow que lo reemplaza, cualquier problema reportarlo
     *
     * @param integer $id
     * @return mixed
     */ 
    public function findRow ( $id = 0 )
    {
        /**
         * valido el id
         */
        $id = (int) $id;
        if( $id != 0 ) {
            if( isset( $this->_sequenceName )) {
                return $this->find( $id )->current();
            } else {
                return $this->fetchRow( $this->_primary[1] . '=' . $id );
            }
        }
        return false;
    }
    public function findAll ( array $filter )
    {
        $select = $this->select();
        foreach( $filter as $name => $value ) {
            $select = $select->where( "$name = ?", $value );
        }
        return $this->fetchAll( $select );
    }
    /* Devuelve el resultado de una consulta con jois entre tablas */
    public function findForFiltersWithJoins ( array $table, array $joins, array $joins_conditions, array $joins_fields, array $filters, array $ant_expressions, array $post_expressions, array $variant )
    {
        // FORM
        $select = $this->select()->setIntegrityCheck(
            false )->distinct()->from(
            array( 
                $table[ 'name' ] => $this->_name 
            ), 
            $table[ 'fields' ] );
        // JOINS
        foreach( $joins as $name => $value ) {
            $select->join(
                array( 
                    $name => $value 
                ), 
                $joins_conditions[ $name ], 
                $joins_fields[ $name ] );
        }
        // WHERE'S
        foreach( $filters as $fillName => $fillValue ) {
            if( ! empty(
                $fillValue ) &&
                ! empty(
                    $fillName ) ) {
                    if( $variant[ $fillName ] ==
                    true ) {
                        $select->where(
                            $ant_expressions[ $fillName ] .
                            ' ' .
                            $fillName .
                            ' ' .
                            $post_expressions[ $fillName ] .
                            ' ? ', 
                            $fillValue );
                } else {
                    $select->where(
                        $ant_expressions[ $fillName ] .
                            ' ' .
                            $fillName .
                            ' ' .
                            $post_expressions[ $fillName ] .
                            ' ' .
                            $fillValue, 
                            $fillValue );
                }
            }
        }
        return $this->fetchAll( $select );
    }
    public function findForFiltersWithExpressions ( array $filters, array $ant_expressions, array $post_expressions, array $variant )
    {
        $select = $this->select();
        foreach( $filters as $fillName => $fillValue ) {
            if( ! empty(
                $fillValue ) &&
                ! empty(
                    $fillName ) ) {
                    if( $variant[ $fillName ] ==
                    true ) {
                        $select->where(
                            $ant_expressions[ $fillName ] .
                            ' ' .
                            $fillName .
                            ' ' .
                            $post_expressions[ $fillName ] .
                            ' ? ', 
                            $fillValue );
                } else {
                    $select->where(
                        $ant_expressions[ $fillName ] .
                            ' ' .
                            $fillName .
                            ' ' .
                            $post_expressions[ $fillName ] .
                            ' ' .
                            $fillValue, 
                            $fillValue );
                }
            }
        }
        return $this->fetchAll( $select );
    }
    public function findFieldWithFilter ( $field, array $filter )
    {
        $select = $this->select()->from( $this->_name, array( $field ));
        foreach( $filter as $name => $value ) {
            if( !empty( $value )){
                $select = $select->where(  "$name = ?", $value );
            }
        }
        $row = $this->fetchRow( $select );
        if( isset(
            $row->$field ) ) {
            return $row->$field;
        }
        return false;
    }
    public function add ( array $data )
    {
        if( $this->_validateData( $data ) ) {
            $id = $this->insert( $data );
           /**
             * Si el modelo tiene un sequences, devuelve el valor siguiente de ese modelo 
             */
            if( isset( $this->_sequenceName )) {
                $id = $this->getAdapter()->lastInsertId( $this->_sequenceName );
            }
            return $id;
        } else {
            return false;
        }
    }
    public function modify ( array $data, $filter )
    {
        return $this->update( $data, $filter ); 
    }
    public function erase ( $filter )
    {
        return $this->delete( $filter );
    }
    protected function _setError ( $description )
    {
        $this->_errors[] = $description;
    }
    /**
     * Valido los datos antes de guardar en la base
     *
     * @param array $data
     * @return boolean si es valido o no
     */
    protected function _validateData ( $data )
    {
        foreach( $data as $field => $value ) {
            if( in_array( $field, $this->_fieldNotEmpty ) && empty( $value ) ) {
                $this->_setError( "El campo $field esta vacio" );
            }
            if( in_array( $field, $this->_fieldInteger ) && 
                ! is_int( intval($value) ) && ! empty( $value ) ) {
                $this->_setError( "El campo $field tiene que ser un entero" );
            }
        }
        if( count( $this->_errors ) ) {
            return false;
        }
        return true;
    }
    /**
     * Devuelve un array con una consulta sql, donde el indice y el value son determinado
     * por los campos que envia el usuario, formando un array $key[$value]
     *
     * @param string $key
     * @param string $value
     * @param string $filter
     * @uses method $this->findAll
     * @return array $arrayResult
     */
    public function getRowsInArray( $key, $value, $filter = array() )
    {
        $arrayResult = array();
        $rows = $this->findAll( $filter );
        foreach( $rows as $row ) {
            if( isset( $row->$key ) && isset( $row->$value ) ) {
                $arrayResult[ $row->$key ] = $row->$value;
            }
        }
        return $arrayResult;
    } 
}
?>
